/*
 * jQuery.splitter.js - animated splitter plugin
 *
 * version 1.0 (2010/01/02) 
 * 
 * Dual licensed under the MIT and GPL licenses: 
 *   http://www.opensource.org/licenses/mit-license.php 
 *   http://www.gnu.org/licenses/gpl.html 
 */

/**
 * jQuery.splitter() plugin implements a two-pane resizable animated window,
 * using existing DIV elements for layout. For more details and demo visit:
 * http://krikus.com/js/splitter
 * 
 * @example $("#splitterContainer").splitter({splitVertical:true,A:$('#leftPane'),B:$('#rightPane'),closeableto:0});
 * @desc Create a vertical splitter with toggle button
 * 
 * @example $("#splitterContainer").splitter({minAsize:100,maxAsize:300,splitVertical:true,A:$('#leftPane'),B:$('#rightPane'),slave:$("#rightSplitterContainer"),closeableto:0});
 * @desc Create a vertical splitter with toggle button, with minimum and maximum
 *       width for plane A and bind resize event to the slave element
 * 
 * @name splitter
 * @type jQuery
 * @param Object
 *            options Options for the splitter ( required)
 * @cat Plugins/Splitter
 * @return jQuery
 * @author Kristaps Kukurs (contact@krikus.com)
 */

;
(function($) {

	$.fn.splitter = function(args) {
		args = args || {};
		return this
				.each(function() {
					var _ghost; // splitbar ghosted element
					var splitPos; // current splitting position
					var _splitPos; // saved splitting position
					var _initPos; // initial mouse position
					var _ismovingNow = false; // animaton state flag

					// Default opts
					var direction = (args.splitHorizontal ? 'h' : 'v');
					var opts = $.extend({
						minAsize : 0, // minimum width/height in PX of the
										// first (A) div.
						maxAsize : 0, // maximum width/height in PX of the
										// first (A) div.
						minBsize : 0, // minimum width/height in PX of the
										// second (B) div.
						maxBsize : 0, // maximum width/height in PX of the
										// second (B) div.
						ghostClass : 'working',// class name for _ghosted
												// splitter and hovered button
						invertClass : 'invert',// class name for invert
												// splitter button
						animSpeed : 250
					// animation speed in ms
					}, {
						v : { // Vertical
							moving : "left",
							sizing : "width",
							eventPos : "pageX",
							splitbarClass : "splitbarV",
							buttonClass : "splitbuttonV",
							cursor : "e-resize"
						},
						h : { // Horizontal
							moving : "top",
							sizing : "height",
							eventPos : "pageY",
							splitbarClass : "splitbarH",
							buttonClass : "splitbuttonH",
							cursor : "n-resize"
						}
					}[direction], args);

					// setup elements
					var splitter = $(this);
					var mychilds = splitter.children(); // $(">*", splitter[0]);
					var A = args.A; // left/top frame
					var B = args.B;// right/bottom frame
					var slave = args.slave;// optional, elemt forced to receive
											// resize event
					// Create splitbar
					var C = $('<div><span></span></div>');
					A.after(C);
					C.attr({
						"class" : opts.splitbarClass,
						unselectable : "on"
					}).css({
						"cursor" : opts.cursor,
						"user-select" : "none",
						"-webkit-user-select" : "none",
						"-khtml-user-select" : "none",
						"-moz-user-select" : "none"
					}).bind("mousedown", startDrag);

					if (opts.closeableto != undefined) {
						var Bt = $('<div></div>').css("cursor", 'pointer');
						C.append(Bt);
						Bt.attr({
							"class" : opts.buttonClass,
							unselectable : "on"
						});
						Bt.hover(function() {
							$(this).addClass(opts.ghostClass);
						}, function() {
							$(this).removeClass(opts.ghostClass);
						});
						Bt.mousedown(function(e) {
							if (e.target != this)
								return;
							Bt.toggleClass(opts.invertClass).hide();
							splitTo((splitPos == opts.closeableto) ? _splitPos
									: opts.closeableto, true);
							return false;
						});
					}
					// reset size to default.
					var perc = (((C.position()[opts.moving] - splitter.offset()[opts.moving]) / splitter[opts.sizing]
							()) * 100).toFixed(1);
					splitTo(perc, false, true);
					// resize event handlers;
					splitter.bind("resize", function(e, size) {
						if (e.target != this)
							return;
						splitTo(splitPos, false, true);
					});
					$(window).bind("resize", function() {
						splitTo(splitPos, false, true);
					});

					// C.onmousedown=startDrag
					function startDrag(e) {
						if (e.target != this)
							return;
						_ghost = _ghost || C.clone(false).insertAfter(A);
						splitter._initPos = C.position();
						splitter._initPos[opts.moving] -= C[opts.sizing]();
						_ghost.addClass(opts.ghostClass).css('position',
								'absolute').css('z-index', '250').css(
								"-webkit-user-select", "none").width(C.width())
								.height(C.height()).css(opts.moving,
										splitter._initPos[opts.moving]);
						mychilds.css("-webkit-user-select", "none"); // Safari
																		// selects
																		// A/B
																		// text
																		// on a
																		// move
						A._posSplit = e[opts.eventPos];

						$(document).bind("mousemove", performDrag).bind(
								"mouseup", endDrag);
					}
					// document.onmousemove=performDrag
					function performDrag(e) {
						if (!_ghost || !A)
							return;
						var incr = e[opts.eventPos] - A._posSplit;
						_ghost.css(opts.moving, splitter._initPos[opts.moving]
								+ incr);
					}
					// C.onmouseup=endDrag
					function endDrag(e) {
						var p = _ghost.position();
						_ghost.remove();
						_ghost = null;
						mychilds.css("-webkit-user-select", "text");// let
																	// Safari
																	// select
																	// text
																	// again
						$(document).unbind("mousemove", performDrag).unbind(
								"mouseup", endDrag);
						var perc = (((p[opts.moving] - splitter.offset()[opts.moving]) / splitter[opts.sizing]
								()) * 100).toFixed(1);
						splitTo(
								perc,
								(splitter._initPos[opts.moving] > p[opts.moving]),
								false);
						splitter._initPos = 0;
					}
					// Perform actual splitting and animate it;
					function splitTo(perc, reversedorder, fast) {
						if (_ismovingNow || perc == undefined)
							return;// generally MSIE problem
						_ismovingNow = true;
						if (splitPos && splitPos > 10 && splitPos < 90)// do
																		// not
																		// save
																		// accidental
																		// events
							_splitPos = splitPos;
						splitPos = perc;

						var barsize = C[opts.sizing]()
								+ (2 * parseInt(C.css('border-' + opts.moving
										+ '-width')));// + border. cehap&dirty
						var splitsize = splitter[opts.sizing]();
						if (opts.closeableto != perc) {
							var percpx = Math.max(parseInt((splitsize / 100)
									* perc), opts.minAsize);
							if (opts.maxAsize)
								percpx = Math.min(percpx, opts.maxAsize);
						} else {
							var percpx = parseInt((splitsize / 100) * perc, 0);
						}
						if (opts.maxBsize) {
							if ((splitsize - percpx) > opts.maxBsize)
								percpx = splitsize - opts.maxBsize;
						}
						if (opts.minBsize) {
							if ((splitsize - percpx) < opts.minBsize)
								percpx = splitsize - opts.minBsize;
						}
						var sizeA = Math.max(0, (percpx - barsize));
						var sizeB = Math.max(0, (splitsize - percpx));
						splitsize = (splitsize - barsize);

						// A.attr('title','- '+sizeA); B.attr('title','-
						// '+sizeB);
						if (fast) {
							A.show().css(opts.sizing, sizeA + 'px');
							B.show().css(opts.sizing, sizeB + 'px');
							Bt.show();
							if (!$.browser.msie) {
								// if(true){
								mychilds.trigger("resize");
								if (slave)
									slave.trigger("resize");
							}
							_ismovingNow = false;
							return true;
						}
						if (reversedorder) {// reduces flickering if total
											// percentage becomes more than 100
											// (possible while animating)
							var anob = {};
							anob[opts.sizing] = sizeA + 'px';
							A.show().animate(anob, opts.animSpeed, function() {
								Bt.fadeIn('fast');
								if ($(this)[opts.sizing]() < 2) {
									this.style.display = 'none';
									B.stop(true, true);
									B[opts.sizing](splitsize + 'px');
								}
							});
							var anob2 = {};
							anob2[opts.sizing] = sizeB + 'px';
							B.show().animate(anob2, opts.animSpeed, function() {
								Bt.fadeIn('fast');
								if ($(this)[opts.sizing]() < 2) {
									this.style.display = 'none';
									A.stop(true, true);
									A[opts.sizing](splitsize + 'px')
								}
							});
						} else {
							var anob = {};
							anob[opts.sizing] = sizeB + 'px';
							B.show().animate(anob, opts.animSpeed, function() {
								Bt.fadeIn('fast');
								if ($(this)[opts.sizing]() < 2) {
									this.style.display = 'none';
									A.stop(true, true);
									A[opts.sizing](splitsize + 'px')
								}
							});
							var anob = {};
							anob[opts.sizing] = sizeA + 'px';
							A.show().animate(anob, opts.animSpeed, function() {
								Bt.fadeIn('fast');
								if ($(this)[opts.sizing]() < 2) {
									this.style.display = 'none';
									B.stop(true, true);
									B[opts.sizing](splitsize + 'px');
								}
							});
						}
						// trigger resize evt
						splitter.queue(function() {
							setTimeout(function() {
								splitter.dequeue();
								_ismovingNow = false;
								mychilds.trigger("resize");
								if (slave)
									slave.trigger("resize");
							}, opts.animSpeed + 5);
						});

					}// end splitTo()

				});// end each
	};// end splitter

})(jQuery);